package com.huatai.datadevelop.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huatai.datadevelop.constant.Constant;
import com.huatai.datadevelop.constant.RedisConstant;
import com.huatai.datadevelop.entity.ApiSuperviseEntity;
import com.huatai.datadevelop.entity.RealApiManageEntity;
import com.huatai.datadevelop.entity.RealApiVonversionEntity;
import com.huatai.datadevelop.entity.SysConfigEntity;
import com.huatai.datadevelop.mapper.RealApiManageMapper;
import com.huatai.datadevelop.thread.service.AsyncServiceExecut;
import com.huatai.datadevelop.utils.*;
import org.apache.commons.lang.StringUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
//import java.util.concurrent.locks.ReentrantLock;
import java.util.stream.Collectors;

/**
 * @author hecai
 * @description: TODO
 * @date 2022/11/29 11:48
 * @Version 1.0
 */
@Service
public class RealApiManageService extends ServiceImpl<RealApiManageMapper, RealApiManageEntity> {

    @Autowired
    private TemplateService templateService;
    @Autowired
    private TokenConfigService tokenConfigService;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private AsyncServiceExecut asyncServiceExecut;
    @Autowired
    private ApiSuperviseService apiSuperviseService;
    @Autowired
    private SysConfigService sysConfigService;
    @Autowired
    private RealApiVonversionService realApiVonversionService;
    @Autowired
    private RealCommonService commonService;
	@Autowired
	private RedissonClient redissonClient;

    //private ReentrantLock lock = new ReentrantLock();

    /**
     * 新增或更新
     * @param data
     * @return
     */
    public Boolean saveOrUpdateManage(RealApiManageEntity data){
        JSONObject jsonBody = data.getJsonBody();
        if(jsonBody!=null && jsonBody.size()>0){
            data.setBody(JSON.toJSONString(jsonBody));
        }
        JSONObject jsonHeard = data.getJsonHeard();
        if(jsonHeard!=null && jsonHeard.size()>0){
            data.setHeard(JSON.toJSONString(jsonHeard));
        }
        return this.saveOrUpdate(data);
    }

    /**
     * 获取新增的接口英文名称是否合规
     *
     * @param interfaceName
     * @return
     */
    public HashMap<String,Object> getInterfaceNameCompliance(String interfaceName) {
        HashMap<String,Object> hashMap = new HashMap<>(2);
        hashMap.put("success",true);
        //判断是否全是英文
        boolean matches = interfaceName.matches("[a-zA-Z]+");
        if(!matches){
            hashMap.put("success",false);
            hashMap.put("message","只能填写英文");
            return hashMap;
        }
        List<String> interfaceNameList = this.list().stream().filter(p->p.getInterfaceName().equals(interfaceName)).map(p -> p.getInterfaceName()).collect(Collectors.toList());
        if (interfaceNameList.size() > 0) {
            hashMap.put("success",false);
            hashMap.put("message","该名称已存在");
            return hashMap;
        }
        hashMap.put("message","验证通过");
        return hashMap;
    }

    /**
     * 分页获取数据
     *
     * @param params
     * @return
     */
    public PageUtils queryPage(Map<String, Object> params) {
        String name = (String) params.get("name");
        IPage<RealApiManageEntity> page = this.page(
                new Query<RealApiManageEntity>().getPage(params),
                new QueryWrapper<RealApiManageEntity>().like(StringUtils.isNotBlank(name), "name", name)
        );
        //方便前端展示，将body参数转化成json格式
        if (page.getPages() > 0) {
            List<RealApiManageEntity> records = page.getRecords();
            records.forEach(p -> {
                String body = p.getBody();
                p.setJsonBody(JSON.parseObject(body));
                p.setJsonKeyReplaceValue(JSON.parseObject(p.getKeyReplaceValue()));
                p.setJsonHeard(JSON.parseObject(p.getHeard()));
            });
        }
        return new PageUtils(page);
    }

    /**
     * 获取第三方接口数据
     */
    public Object asyncRequestApi(JSONObject data, RealApiManageEntity apiManageEntity) {
        //TODO 此处还差锁机制，让当前参数处理完之后在处理下一个请求
        String type = "实时数据接口配置";
        List<String> pathList = new CopyOnWriteArrayList<String>();
        String method = apiManageEntity.getMethod();
        String heard = apiManageEntity.getHeard();
        Map<String, String> heardMap = new ConcurrentHashMap<String,String>();
        if(StringUtils.isNotBlank(heard)){
            heardMap = JSON.parseObject(heard,HashMap.class);
        }else {
            heardMap = InitHashMapUtil.InitHashMapJSON();
        }
        Object object = null;
        Object fetchData = null;
        String redisKey = RedisKeys.getRealApiKey(apiManageEntity.getInterfaceName());

        //记录接口状态
        ApiSuperviseEntity apiSuperviseEntity = new ApiSuperviseEntity();
        try{
            ApiSuperviseEntity interface_name = this.apiSuperviseService.getOne(new QueryWrapper<ApiSuperviseEntity>()
                    .eq("interface_name", apiManageEntity.getInterfaceName())
            .eq("type",type));
            if(interface_name!=null){
                apiSuperviseEntity = interface_name;
            }
        }catch (Exception ex){}
        apiSuperviseEntity.setInterfaceName(apiManageEntity.getInterfaceName());
        apiSuperviseEntity.setName(apiManageEntity.getName());
        apiSuperviseEntity.setUrl(apiManageEntity.getUrl());
        apiSuperviseEntity.setType(type);
		RLock lock = redissonClient.getLock(RedisConstant.PERMISSION_LOCK);
		lock.lock();
        try{
            if(method.equalsIgnoreCase("GET")){
                object = this.getGetRequestData(data,apiManageEntity,heardMap);
            }else {
                object = this.getPostRequestData(data,apiManageEntity,heardMap);
            }

            String dataPath = apiManageEntity.getDataPath();
            String[] split = dataPath.split("\\.");
            for (String str : split) {
                pathList.add(str);
            }
            fetchData = this.recursionFetchData(object, pathList);
            //TODO 此处还差取出指定字段的json 一个或个多

            //判断是否默认取第一条数据
            if(apiManageEntity.getFirstOne().equalsIgnoreCase(Constant.TRUE)){
                fetchData = this.getFirstOneData(fetchData);
            }
            //判断是否需要对字符串进行替换
            if(apiManageEntity.getKeyReplace().equalsIgnoreCase(Constant.TRUE)){
                fetchData = keyReplaceValueData(fetchData,JSON.parseObject(apiManageEntity.getKeyReplaceValue(),HashMap.class));
            }

            //判断是否需要对值进行转换
            Object realApiConversionObject = redisCache.get(RedisKeys.getRealApiConversionKey(apiManageEntity.getId().toString()));
            if(realApiConversionObject!=null){
                List<RealApiVonversionEntity> realApiVonversionEntityList = JSON.parseArray(realApiConversionObject.toString(), RealApiVonversionEntity.class);
                if(realApiVonversionEntityList.size()>0){
                    fetchData = commonService.getDataConversionMapOtList(realApiVonversionEntityList,fetchData);
                }
            }

            //异步线程，将数据写入缓存中
            if(apiManageEntity.getRedisNeed().equals(Constant.TRUE)){
                asyncServiceExecut.executorService(fetchData,redisKey,redisCache);
            }

        }catch (Exception ex){
            log.error("数据请求异常，走缓存，错误信息如下："+ex.getMessage());
            //TODO 异常处理
            apiSuperviseEntity.setStatus(Constant.ABNORMAL);
            apiSuperviseEntity.setReason(ex.getMessage());
            //异常情况下若配置走了缓存，则先查看缓存数据库，若不配置，则直接返回null
            String redisNeed = apiManageEntity.getRedisNeed();
            if(redisNeed.equals(Constant.TRUE)){
                Object value = redisCache.get(redisKey);
                if(value!=null){
                    switch (apiManageEntity.getDataType()){
                        case "ArrayList":
                            fetchData =JSON.parseArray(value.toString(),Object.class);
                            break;
                        case "LinkedHashMap":
                            fetchData =JSON.parseObject(value.toString());
                            break;
                        default:
                            fetchData = value;
                            break;
                    }
                }else {
                    fetchData = null;
                }

            }else {
                fetchData = null;
            }
        }
        finally {
            lock.unlock();
            apiSuperviseEntity.setSuperviseTime(new Date());
            apiSuperviseService.executorService(apiSuperviseEntity);
        }
        return fetchData;
    }

    /**
     * 需要替换值
     * @param fetchData
     * @param keyValue
     * @return
     */
    public Object keyReplaceValueData(Object fetchData,HashMap<String,String> keyValue){
        if(keyValue.size()>0){

            String strJSON = JSON.toJSONString(fetchData);
            for (Map.Entry<String, String> map : keyValue.entrySet()) {
                strJSON = strJSON.replaceAll(map.getKey(),map.getValue());
            }
            //数据是列表数据的处理
            if(fetchData instanceof ArrayList){
                List<Object> objectList = JSON.parseArray(strJSON, Object.class);
                return objectList;
            }
            else {
                Object parse = JSON.parse(strJSON);
                return parse;
            }
        }
        return null;
    }

    /**
     * 是否取第一条
     */
    public Object getFirstOneData(Object fetchData){
        List<Object> objectList = JSON.parseArray(JSON.toJSONString(fetchData), Object.class);
        if(objectList!=null && objectList.size()>0){
            return objectList.get(0);
        }
        return null;
    }

    /**
     * 获取post请求参数配置
     * @param data
     * @param apiManageEntity
     * @return
     */
    public Object getPostRequestData(Map<String,Object> data, RealApiManageEntity apiManageEntity, Map<String, String> heardMap) {
        String body = apiManageEntity.getBody();
        Map<String,Object> mapData = new HashMap<>();
        if (StringUtils.isNotBlank(body)) {
            mapData = JSON.parseObject(body);
        }
        for (Map.Entry<String,Object> map:data.entrySet()){
            String key = map.getKey();
            Object value = map.getValue();
            mapData.put(key,value);
        }
        //TODO 后续需要逻辑处理

        return this.getCommonRequest(mapData,apiManageEntity,heardMap,apiManageEntity.getMethod());
    }

    /**
     * 获取get请求参数配置
     * @param data
     * @param apiManageEntity
     * @return
     */
    public Object getGetRequestData(Map<String,Object> data, RealApiManageEntity apiManageEntity, Map<String, String> heardMap) {
        //TODO 后续需要处理的get逻辑放置在此处
        //get请求参数配置
        String param = apiManageEntity.getParam();
        StringBuilder stringBuilder = new StringBuilder();
        for (Map.Entry<String,Object> map:data.entrySet()){
            String key = map.getKey();
            Object value = map.getValue();
            stringBuilder.append(key).append("=").append(value).append("&");
        }
        param = param + stringBuilder.toString();
        if(StringUtils.isNotBlank(param)){
            param = param.substring(0,param.length()-1);
            apiManageEntity.setUrl(apiManageEntity.getUrl() + "?" + param);
        }
        return this.getCommonRequest(data,apiManageEntity,heardMap,"GET");
    }

    /**
     * 数据统一出口
     * @param data
     * @param apiManageEntity
     * @param heardMap
     * @param method
     * @return
     */
    public Object getCommonRequest(Map<String,Object> data, RealApiManageEntity apiManageEntity, Map<String, String> heardMap,String method){
        //判断是否需要token
        String needToken = apiManageEntity.getNeedToken();
        if(needToken.equalsIgnoreCase(Constant.TRUE)){
            String token = apiManageEntity.getTokenPrefix() + this.tokenConfigService.getApiTokenByBody(apiManageEntity.getTokenId());
            String tokenPath = apiManageEntity.getTokenPath();
            String tokenData = apiManageEntity.getTokenData();
            //TODO 处理token
            switch (tokenPath) {
                case "heard":
                    heardMap.put(tokenData, token);
                    break;
                case "body":
                    data.put(tokenData, token);
                    break;
                case "param":
                    String param = tokenData + "=" + token;
                    apiManageEntity.setUrl(apiManageEntity.getUrl() + param);
                    break;
            }
        }

        String body = apiManageEntity.getBody();
        JSONObject jsonObject = JSON.parseObject(body);
        if(data!=null && data.size()>0){
            for (Map.Entry<String, Object> stringStringEntry : data.entrySet()) {
                jsonObject.put(stringStringEntry.getKey(), stringStringEntry.getValue());
            }
        }

        Object object= method.equalsIgnoreCase("GET")?
                this.templateService.get(apiManageEntity.getUrl(),heardMap,Object.class)
                :
                this.templateService.postByModelExchange(apiManageEntity.getUrl(), heardMap, data, Object.class);
        return object;
    }

    /**
     * 递归取数据
     *
     * @param object
     * @param path
     * @return
     */
    public Object recursionFetchData(Object object, List<String> path) {
        Object data = null;
        if(object!=null){
            String keyPath = path.get(0);
            data = ((LinkedHashMap) object).get(keyPath);
            if(path.size() != 1){
                path.remove(0);
                return recursionFetchData(data,path);
            }
        }
        return data;
    }

    /**
     * 根据接口名称获取数据
     * @param interfaceName
     * @return
     */
    public RealApiManageEntity getEntityByInterfaceName(String interfaceName){
        QueryWrapper<RealApiManageEntity> qw = new QueryWrapper<>();
        qw.eq("interface_name",interfaceName);
        RealApiManageEntity one = this.getOne(qw);
        return one;
    }

    //值替换 值脱敏 时间转换

    /**
     * 获取配置数据的值域
     * @return
     */
    public List<String> getConversionKey(String key) {
        QueryWrapper qw = new QueryWrapper<SysConfigEntity>();
        qw.eq("param_key",key);
        List<SysConfigEntity> list = sysConfigService.list(qw);
        return list.stream().map(p->p.getParamValue()).distinct().collect(Collectors.toList());
    }

    /**
     * 保存或更新数据
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveOrUpdateConversion(List<RealApiVonversionEntity> entity, String id){
        this.realApiVonversionService.saveOrUpdateBatch(entity);
        this.redisCache.set(RedisKeys.getRealApiConversionKey(id),JSON.toJSONString(entity),-1L);
    }

    /**
     * 获取已经配置了的数据
     * @return
     */
    public List<RealApiVonversionEntity> getConversionList(String realapiId) {
        QueryWrapper qw = new QueryWrapper<RealApiVonversionEntity>();
        qw.eq("realapi_id",realapiId);
        List<RealApiVonversionEntity> dataList = this.realApiVonversionService.list(qw);
        return dataList;
    }
}
